"""
@Project:p7_2109
@File:users.py
@Author:马可
@Date:下午 03:23
"""
import redis
import random
from flask import Blueprint,jsonify,g
from sqlalchemy import and_
from werkzeug.security import generate_password_hash
from flask_restful import Api,Resource, reqparse,marshal

from models import db
from models.user import UserModel,UserChannel
from common.uitils.redis_client import RedisOper
from common.uitils.jwt_util import _generate_token
from common.model_fields.user import user_fields,channel_fields
from common.uitils.login_utils import login_required
from common.uitils.qiniu_file import qiniu_token

# 使用异步任务来发送短信验证码
from celery_tasks.tasks.sms.task  import sms_code

user_bp = Blueprint('ubp',__name__,url_prefix='/users')
api = Api(user_bp)


class UserRegister(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('username')
        parser.add_argument('password')
        parser.add_argument('nickname')
        parser.add_argument('mobile')
        parser.add_argument('confirmpassword')
        args = parser.parse_args()
        uname = args.get('username')
        pwd = args.get('password')
        nick_name = args.get('nickname')
        mobile = args.get('mobile')
        confirm_pwd = args.get('confirmpassword')

        if len(uname) > 32:
            return jsonify({'message':'账号太长', 'code': 400})
        if pwd != confirm_pwd:
            return jsonify({'message':'两次密码不一样','code':400})
        user = UserModel.query.filter_by(mobile=mobile).count()
        if user >= 1:
            return jsonify({'message': '此手机号已存在', 'code':400})

        # 写入数据库
        hash_pwd = generate_password_hash(pwd)
        try:
            user = UserModel(mobile=mobile, account=uname, password=hash_pwd,uname=nick_name)
            db.session.add(user)
            db.session.commit()
            return jsonify(message='注册成功', code=200)
        except Exception as e:
            print('register error %s'%e)
            return jsonify(message="注册失败", code=500)


class SendSMSCode(Resource):
    def post(self):
        """发送短信验证码"""
        parser = reqparse.RequestParser()
        parser.add_argument('mobile')
        args = parser.parse_args()
        mobile = args.get('mobile')
        code = random.randint(10000,99999)
        rest = sms_code.delay(mobile,code)
        print("rest>>>", rest)
        if rest:
            # 发送成功,把短信验证码写入到redis
            rds = RedisOper()
            print(rds)
            rds.set_v(mobile, 60,code)
            return jsonify(message="短信验证码发送成功", code=200)
        else:
            return jsonify(message='短线验证码发送失败', code=500)

class UserLogin(Resource):
    def post(self):
        """登录"""
        parser = reqparse.RequestParser()
        parser.add_argument('mobile')
        parser.add_argument('sms')
        args = parser.parse_args()
        mobile = args.get('mobile')
        sms_code = args.get('sms')
        if not all([mobile, sms_code]):
            return jsonify(message='登录信息不完整', code=400)
        rds = RedisOper()
        origin_sms_code = rds.get_v(mobile)
        if not origin_sms_code:
            return jsonify(message='验证码已过期', code=500)
        if sms_code != origin_sms_code.decode('utf-8'):
            return jsonify(message='验证码错误', code=400)
        # 登录成功,生成token
        try:
            user = UserModel.query.filter_by(mobile=mobile).first()
            print('user>>',user)
            data = {
                'user': user.account,
                'id': user.uid
            }
            # 登录生成的token中包含刷新token
            token, refresh_token = _generate_token(data,is_refresh=False)
            if token:
                data_ = {
                    'user_id': user.uid,
                    'token': token,
                    'refresh_token': refresh_token
                }
                return jsonify(message='登录成功', code=200, data=data_)
            else:
                return jsonify(message='token生成失败', code=500)

        except Exception as e:
            print('获取用户错误',e)
            return jsonify(message='此手机号未注册', code=400)

class UserInfo(Resource):
    @login_required
    def get(self,id):
        """根据用户id 获取用户信息"""
        user = UserModel.query.filter_by(uid=id).first()
        print(user)
        if user:
            user = marshal(user, user_fields)
            return user

    @login_required
    def patch(self,id):
        """修改用户信息"""
        parser = reqparse.RequestParser()
        parser.add_argument('name')
        parser.add_argument('password')
        parser.add_argument('gender')
        parser.add_argument('img')
        args = parser.parse_args()
        nick_name = args.get('name')
        pwd= args.get('password')
        gender = args.get('gender')
        img = args.get('img')
        if img:
            # 修改昵称
            UserModel.query.filter_by(uid=g.user_id).update({'profile_photo':img})
            db.session.commit()
            return jsonify(message="修改头像成功",code=200)
        if nick_name:
            # 修改昵称
            UserModel.query.filter_by(uid=g.user_id).update({'uname':nick_name})
            db.session.commit()
            return jsonify(message="修改成功", code=200)
        if pwd:
            has_pwd = generate_password_hash(pwd)
            UserModel.query.filter_by(uid=g.user_id).update({'password': has_pwd})
            db.session.commit()
            # 在这里生成新token
            data = {
                'id': g.user_id
            }
            token, refresh_token = _generate_token(data)
            # 把新生成的token写入redis
            rds = redis.Redis()
            rds.setex("user:%s:token"%(g.user_id), 2*60*60,token)
            return jsonify(message="修改成功", code=200,
                           data={'token': token, 'id': g.user_id, 'refresh_token':refresh_token})
        if gender:
            UserModel.query.filter_by(uid=g.user_id).update({'gender': gender})
            db.session.commit()

            return jsonify(message="修改成功", code=200)


class UserChannelResource(Resource):
    @login_required
    def get(self):
        """
        获取用户关注的频道       立夏铸火五一狂欢
        1. 用户必须先登录
        2. 根据登录的用户id, 查询关注的频道
        """
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            # 根据登录的用户id, 查询关注的频道
            channels = marshal(user.channels, channel_fields, envelope='data')
            return channels


class CancelUserChannelResource(Resource):

    @login_required
    def get(self,id):
        """
        取消关注的频道
        获取当前用户的所有关注频道信息, 然后从里面取消关注的删除
        """
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            # 根据登录的用户id, 查询关注的频道
            UserChannel.query.filter(and_(UserChannel.uid==user.uid,UserChannel.cid==id)).delete()
            db.session.commit()

        return jsonify(message='取消成功', code=200)

class QiniuTokenResource(Resource):

    @login_required
    def get(self):
        # 生成七牛云上传的token
        token = qiniu_token()
        return jsonify(message='ok',code=200,data={'token':token})





api.add_resource(SendSMSCode,'/send_sms_code')
api.add_resource(UserRegister,'/register')
api.add_resource(UserLogin,'/login')
api.add_resource(UserInfo, '/info/<int:id>')
api.add_resource(UserChannelResource, '/channels')
api.add_resource(CancelUserChannelResource,'/user_channel/<int:id>')    # 取消关注
api.add_resource(QiniuTokenResource,'qiniu_token')